package com.chessimo.main;

import com.chessimo.util.Constant;

/**
 * @author Sergio Batista
 * 
 *         Summary: This class controls all actions in the board: set a
 *         position, validate a move, make a move etc... Public methods are: -
 *         Board() - Change_Player():void -
 *         Get_All_Valid_Moves(boolean):String[] - Get_Num_Move():int -
 *         Get_Player():int - Get_Position():String - Make_Move(String):boolean
 *         - Print_Board():void - Set_Board_Initial():void -
 *         Set_Position(String):void
 * 
 *         How to access this class, Ex: Board b = new Board();
 *         b.Set_Position("2kr2nr/1pp1B1pp/p1p5/4p3/6q1/8/PP3PPP/RN1R2K1 w - - 0 2"
 *         ); String xis[] = b.Get_All_Valid_Moves (true); if
 *         (b.Make_Move("Rxd8#")) { System.out.println(move + " = Good Move"); }
 *         else { System.out.println(move + " = Bad Move"); }
 *         System.out.println("\n==>" + b.Get_Position() + "\n");
 */
public class Board {

	// Represent the board in the current position
	public int board[] = new int[64];

	// Color of each square: WHITE (10) or BLACK (20)
	private static int sqColor[] = new int[64];

	// Algebric of each square Ex: [0]=a8, [1]=b8, [2]=c8 etc...
	private static String sqAlg[] = new String[64];

	// WHITE (10) or BLACK (20)
	private static int whoPlays;

	// Store the last en_passant square in algebric format
	private static String enPassant = "";

	// TRUE if the current move is a promotion
	private static boolean isPromotion;

	// Store the number of moves after the last pawn movement or a take
	private static int numMovesLastPawn;

	// Store the number of moves played at the current position
	private static int numMove;

	private static boolean whiteCanCastleShort = false;
	private static boolean whiteCanCastleLong = false;
	private static boolean blackCanCastleShort = false;
	private static boolean blackCanCastleLong = false;
	public static int squareFrom;
	public static int squareTo;

	/**
	 * Constructor - Create auxiliary arrays and set the board to initial
	 * position Parameters: There are no parameters Return: Nothing
	 */
	public Board() {
		setBoardInitial();
	}

	/**
	 * Set the Board to initial position and reset all information related to it
	 * Parameters: None Return: Nothing
	 */
	public void setBoardInitial() {
		resetBoard();
		setSquareColors();
		setAlgebric();
		whoPlays = Constant.WHITE;

		int tab[] = { Constant.BLACK_ROOK, Constant.BLACK_KNIGHT,
				Constant.BLACK_BISHOP, Constant.BLACK_QUEEN,
				Constant.BLACK_KING, Constant.BLACK_BISHOP,
				Constant.BLACK_KNIGHT, Constant.BLACK_ROOK,
				Constant.BLACK_PAWN, Constant.BLACK_PAWN, Constant.BLACK_PAWN,
				Constant.BLACK_PAWN, Constant.BLACK_PAWN, Constant.BLACK_PAWN,
				Constant.BLACK_PAWN, Constant.BLACK_PAWN, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.FREE_SQUARE,
				Constant.FREE_SQUARE, Constant.WHITE_PAWN, Constant.WHITE_PAWN,
				Constant.WHITE_PAWN, Constant.WHITE_PAWN, Constant.WHITE_PAWN,
				Constant.WHITE_PAWN, Constant.WHITE_PAWN, Constant.WHITE_PAWN,
				Constant.WHITE_ROOK, Constant.WHITE_KNIGHT,
				Constant.WHITE_BISHOP, Constant.WHITE_QUEEN,
				Constant.WHITE_KING, Constant.WHITE_BISHOP,
				Constant.WHITE_KNIGHT, Constant.WHITE_ROOK };

		for (int i = 0; i < 64; i++) {
			board[i] = tab[i];
		}

		whiteCanCastleShort = true;
		whiteCanCastleLong = true;
		blackCanCastleShort = true;
		blackCanCastleLong = true;
		enPassant = "";
		numMovesLastPawn = 0;
		numMove = 1;

	}

	/**
	 * @param fen
	 *            Set a new position at the board Parameters: The position in
	 *            FEN notation
	 */
	public boolean setPosition(String fen) {

		resetBoard();

		// Check if fen is valid
		boolean xis = validateFen(fen);

		if (xis) {
			// Divide the fen notation and handle each chunk in a separate
			// function
			String part[] = splitFEN(fen);
			setPosPieces(part[0]);
			setPosWhoPlays(part[1]);
			setPosCastle(part[2]);
			setPosEnPassant(part[3]);
			setPosNumMovesLastPawn(part[4]);
			setPosNumMoves(part[5]);
			return true;
		} else {
			// If fen is invalid set the board to initial position
			return false;
		}

	}

	/**
	 * @return
	 */
	public String[] getArrayPosition() {

		String[] b = new String[64];

		for (int i = 0; i < 64; i++) {

			if (board[i] == Constant.WHITE_KING) {
				b[i] = "K";
			} else if (board[i] == Constant.WHITE_QUEEN) {
				b[i] = "Q";
			} else if (board[i] == Constant.WHITE_ROOK) {
				b[i] = "R";
			} else if (board[i] == Constant.WHITE_BISHOP) {
				b[i] = "B";
			} else if (board[i] == Constant.WHITE_KNIGHT) {
				b[i] = "N";
			} else if (board[i] == Constant.WHITE_PAWN) {
				b[i] = "P";
			} else if (board[i] == Constant.BLACK_KING) {
				b[i] = "k";
			} else if (board[i] == Constant.BLACK_QUEEN) {
				b[i] = "q";
			} else if (board[i] == Constant.BLACK_ROOK) {
				b[i] = "r";
			} else if (board[i] == Constant.BLACK_BISHOP) {
				b[i] = "b";
			} else if (board[i] == Constant.BLACK_KNIGHT) {
				b[i] = "n";
			} else if (board[i] == Constant.BLACK_PAWN) {
				b[i] = "p";
			} else {
				b[i] = "";
			}
		}
		return b;
	}


	/**
	 * Returns the current position in a FEN string Parameters: None Return: A string with the
	 * position in a FEN format
	 */
	public String getPosition() {

		int ind;
		int freeSquares;
		String fen = "";
		String canCastle = "";

		for (int i = 0; i < 8; i++) { // part 1 = Set up the board position
			freeSquares = 0;
			for (int j = 0; j < 8; j++) {
				ind = (i * 8) + j;
				if (board[ind] != Constant.FREE_SQUARE) {
					if (freeSquares > 0) {
						fen = fen + freeSquares;
						freeSquares = 0;
					}
				}
				switch (board[ind]) {
				case Constant.WHITE_KING:
					fen = fen + "K";
					break;
				case Constant.WHITE_QUEEN:
					fen = fen + "Q";
					break;
				case Constant.WHITE_ROOK:
					fen = fen + "R";
					break;
				case Constant.WHITE_BISHOP:
					fen = fen + "B";
					break;
				case Constant.WHITE_KNIGHT:
					fen = fen + "N";
					break;
				case Constant.WHITE_PAWN:
					fen = fen + "P";
					break;
				case Constant.BLACK_KING:
					fen = fen + "k";
					break;
				case Constant.BLACK_QUEEN:
					fen = fen + "q";
					break;
				case Constant.BLACK_ROOK:
					fen = fen + "r";
					break;
				case Constant.BLACK_BISHOP:
					fen = fen + "b";
					break;
				case Constant.BLACK_KNIGHT:
					fen = fen + "n";
					break;
				case Constant.BLACK_PAWN:
					fen = fen + "p";
					break;
				case Constant.FREE_SQUARE:
					freeSquares++;
					break;
				}
			}
			if (freeSquares > 0) {
				fen = fen + freeSquares;
			}
			if (i < 7) {
				fen = fen + "/";
			}

		}

		if (whoPlays == Constant.WHITE) { // part 2 = Set up who plays
			fen = fen + " " + "w";
		} else {
			fen = fen + " " + "b";
		}

		if (whiteCanCastleShort) { // part 3 = Set up castle information
			canCastle = "K";
		}
		if (whiteCanCastleLong) {
			canCastle = canCastle + "Q";
		}
		if (blackCanCastleShort) {
			canCastle = canCastle + "k";
		}
		if (blackCanCastleLong) {
			canCastle = canCastle + "q";
		}

		if (canCastle == "") {
			canCastle = "-";
		}

		fen = fen + " " + canCastle;

		if (enPassant != "") { // part 4 = Set up en_passant square (if exists)
			fen = fen + " " + enPassant;
		} else {
			fen = fen + " -";
		}

		fen = fen + " " + numMovesLastPawn; // part 5 = Set up the 50 moves rule
											// information
		fen = fen + " " + numMove; // part 6 = Set up the num_moves control

		return fen;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Return the current
	 * player Parameters: None Return: 10 if who plays is WHITE, 20 for BLACK
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	public int getPlayer() {

		return whoPlays;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Change the current
	 * player Parameters: None Return: None Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	public void changePlayer() {

		if (whoPlays == Constant.WHITE) {
			whoPlays = Constant.BLACK;
		} else {
			whoPlays = Constant.WHITE;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the Number of the
	 * current move Parameters: None Return: The number of the current move
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	public int getNumMove() {

		return numMove;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validate and Make a move
	 * at the board Parameters: The move in algebric notation Return: TRUE if
	 * the move could be made. Author: Sergio Batista Date: 31-jan-2012
	 */
	public boolean makeMove(String move) {

		move = cleanNotation(move);

		if (move.equals("O-O")) { // if castle, perform appropriate function
			boolean ret = makeShortCastle();
			return ret;
		} else if (move.equals("O-O-O")) {
			boolean ret = makeLongCastle();
			return ret;
		}

		char z, zCol, zRow;
		int from, to, i;
		String square;
		int newPiece;
		int piece = getPiece(move);
		int x[] = getPieceSquare(piece, move); // Where is the piece to move
												// from? Get all squares of the
												// given piece.
		if (x[0] == Constant.ERROR) { // Piece not found
			return false;
		}

		int pos = move.indexOf("=");
		if (pos > 0) { // is a promotion
			for (i = 9; i >= 0; i--) { // Get the pawn that is near the target
										// line
				if (x[i] > 0) {
					break;
				}
			}
			from = x[i];

			newPiece = getPiece(move.substring(move.length() - 1)); // What
																	// piece the
																	// pawn has
																	// become

			square = move.substring(pos - 2, pos);
			to = getSquareNumber(square);
			if (moveIsValid(Constant.PAWN, from, to)) {
				if (kingIsInCheck(from, to)) {
					return false;
				}
				controlFiftyMovesRule(from, to);
				controlCastle(from, to);
				board[from] = newPiece + whoPlays;
				moveOnBoard(from, to);
				if (whoPlays == Constant.BLACK) {
					numMove++;
				}
				changePlayer();
				return true;
			}
			return false;
		}

		square = move.substring(move.length() - 2); // Get the algebric of the
													// target square
		to = getSquareNumber(square); // Get the number of the target square

		if (move.length() > 3) { // if two pieces can go to the same square, use
									// column or row especification to clarify
									// (Ex: Nbd7)
			z = move.charAt(1);
			boolean ret = (z >= 'a' && z <= 'h' || z >= '1' && z <= '8');
			if (ret) {
				for (i = 0; i < x.length; i++) {
					if (x[i] != Constant.ERROR) {
						zCol = getColumn(x[i]);
						zRow = getRow(x[i]);
						if (z != zCol && z != zRow) {
							x[i] = Constant.ERROR;
						}
					}
				}
			}
		}

		for (i = 0; i < x.length; i++) { // for each piece found, check for a
											// valid move
			if (x[i] != Constant.ERROR) {
				from = x[i];
				if (moveIsValid(piece, from, to)) {
					if (kingIsInCheck(from, to)) {
						return false;
					}
					controlFiftyMovesRule(from, to);
					controlCastle(from, to);
					moveOnBoard(from, to);
					if (whoPlays == Constant.BLACK) {
						numMove++;
					}
					changePlayer();
					return true;
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get all valid moves at
	 * the actual position Parameters: Since this function is recursive, a TRUE
	 * or FALSE parameter is necessary to check the next deep when calling the
	 * function King_Is_In_Check. Once the King_Is_In_Check function is testing
	 * King capture, it's not necessary to see again if the resultants moves are
	 * in check. Return: An array with all valid moves in algebric notation
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	public String[] getAllValidMoves(boolean lookForCheck) {

		/*
		 * if look_for_check is true, this function call King_Is_In_Check to see
		 * if, after the move, the own king is being attacked if look_for_check
		 * is false, then the moves generated will be used only for see if the
		 * own king is being attacked, in a given position
		 */

		int piece;
		int ind = 0;
		String movShort[] = new String[Constant.MAX_VALID_MOVES]; // array to
																	// store the
		// moves in short
		// notation Ex: Re8
		String movLong[] = new String[Constant.MAX_VALID_MOVES]; // array to
																	// store the
		// moves in long
		// notation Ex: Re1-e8
		boolean castleShort = false; // flag to control the function must
										// generate O-O
		boolean castleLong = false; // flag to control the function must
									// generate O-O-O

		/*
		 * This loop scan the board and try to move every piece on board to any
		 * available square (only the pieces with the same color of who_plays is
		 * considered) The first FOR (i) scan the source squares, the second FOR
		 * (j) looks for the target squares Every possible move is validate and
		 * if it is OK, its is stored in two arrays (one for short and one for
		 * long notation)
		 */
		for (int i = 0; i < 64; i++) {
			if (board[i] != Constant.FREE_SQUARE) {
				piece = board[i] - whoPlays;
				if (piece > 0 && piece < 7) {
					for (int j = 0; j < 64; j++) {

						if (moveIsValid(piece, i, j)) {
							if (piece == Constant.PAWN
									&& ((whoPlays == Constant.WHITE && j < 8) || whoPlays == Constant.BLACK
											&& j > 55)) {
								isPromotion = true;
								if (lookForCheck) {
									if (!kingIsInCheck(i, j)) { // As a
																// promotion,
																// creates a
																// move for each
																// promoted
																// piece
										movShort[ind] = convertMoveShort(
												Constant.QUEEN, i, j);
										movLong[ind] = convertMoveLong(
												Constant.QUEEN, i, j);
										ind++;
										movShort[ind] = convertMoveShort(
												Constant.ROOK, i, j);
										movLong[ind] = convertMoveLong(
												Constant.ROOK, i, j);
										ind++;
										movShort[ind] = convertMoveShort(
												Constant.BISHOP, i, j);
										movLong[ind] = convertMoveLong(
												Constant.BISHOP, i, j);
										ind++;
										movShort[ind] = convertMoveShort(
												Constant.KNIGHT, i, j);
										movLong[ind] = convertMoveLong(
												Constant.KNIGHT, i, j);
										ind++;
									}
								} else { // As a promotion, creates a move for
											// each promoted piece
									movShort[ind] = convertMoveShort(
											Constant.QUEEN, i, j);
									movLong[ind] = convertMoveLong(
											Constant.QUEEN, i, j);
									ind++;
									movShort[ind] = convertMoveShort(
											Constant.ROOK, i, j);
									movLong[ind] = convertMoveLong(
											Constant.ROOK, i, j);
									ind++;
									movShort[ind] = convertMoveShort(
											Constant.BISHOP, i, j);
									movLong[ind] = convertMoveLong(
											Constant.BISHOP, i, j);
									ind++;
									movShort[ind] = convertMoveShort(
											Constant.KNIGHT, i, j);
									movLong[ind] = convertMoveLong(
											Constant.KNIGHT, i, j);
									ind++;
								}
								isPromotion = false;
							} else { // store the move in short and long
										// notation
								if (lookForCheck) {
									if (!kingIsInCheck(i, j)) {
										movShort[ind] = convertMoveShort(piece,
												i, j);
										movLong[ind] = convertMoveLong(piece,
												i, j);
										ind++;
									}
								} else {
									movShort[ind] = convertMoveShort(piece, i,
											j);
									movLong[ind] = convertMoveLong(piece, i, j);
									ind++;
								}
							}
						}
					}
				}
			}
		}

		if (lookForCheck) {
			if (!kingIsInCheck()) {
				if (whoPlays == Constant.WHITE) {
					castleShort = whiteCastleShort();
					castleLong = whiteCastleLong();
				} else {
					castleShort = blackCastleShort();
					castleLong = blackCastleLong();
				}
			}
		}

		if (castleShort) {
			movShort[ind] = "O-O";
			movLong[ind] = "O-O";
			ind++;
		}

		if (castleLong) {
			movShort[ind] = "O-O-O";
			movLong[ind] = "O-O-O";
			ind++;
		}

		return checkForDuplicity(movShort, movLong, ind); // fix notation when
															// two (or more)
															// pieces can go for
															// the same square

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Print the current
	 * position of the board. (Only for Test purposes) Parameters: None Return:
	 * Nothing Author: Sergio Batista Date: 31-jan-2012
	 */
	public void printBoard() {

		int ind;

		for (int i = 0; i < 8; i++) {
			System.out.println();
			for (int j = 0; j < 8; j++) {
				ind = (i * 8) + j;
				switch (board[ind]) {
				case Constant.WHITE_KING:
					System.out.print(" K ");
					break;
				case Constant.WHITE_QUEEN:
					System.out.print(" Q ");
					break;
				case Constant.WHITE_ROOK:
					System.out.print(" R ");
					break;
				case Constant.WHITE_BISHOP:
					System.out.print(" B ");
					break;
				case Constant.WHITE_KNIGHT:
					System.out.print(" N ");
					break;
				case Constant.WHITE_PAWN:
					System.out.print(" O ");
					break;
				case Constant.BLACK_KING:
					System.out.print(" k ");
					break;
				case Constant.BLACK_QUEEN:
					System.out.print(" q ");
					break;
				case Constant.BLACK_ROOK:
					System.out.print(" r ");
					break;
				case Constant.BLACK_BISHOP:
					System.out.print(" b ");
					break;
				case Constant.BLACK_KNIGHT:
					System.out.print(" n ");
					break;
				case Constant.BLACK_PAWN:
					System.out.print(" o ");
					break;
				default:
					System.out.print(" . ");
					break;
				}
			}
		}

		System.out.println();
		System.out.println();

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Verify if the King is in
	 * check at the actual position Parameters: There are no parameters Return:
	 * TRUE if the King is in check, otherwise return FALSE Author: Sergio
	 * Batista Date: 31-jan-2012
	 */
	private boolean kingIsInCheck() {

		boolean isCheck = false; // Assuming the King is not in check
		String target; // The algebric square to analyse

		changePlayer();
		String kingSquare = getKingSquare();
		String[] tabMoves = getAllValidMoves(false); // Get all valid moves for
														// the adversary

		for (int i = 0; i < tabMoves.length; i++) { // Check if each adversary
													// move can go at the king
													// square
			if (tabMoves[i] == null) {
				break;
			}
			target = tabMoves[i].substring(tabMoves[i].length() - 2);
			if (target.equals(kingSquare)) {
				isCheck = true;
				break;
			}
		}

		changePlayer(); // Get the correct player back
		if (isCheck) {
			return true;
		} else {
			return false;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Verify if the King is in
	 * check after a certain move Parameters: The squares numbers of FROM and TO
	 * Return: TRUE if the King is in check, otherwise return FALSE Author:
	 * Sergio Batista Date: 31-jan-2012
	 */
	private boolean kingIsInCheck(int from, int to) {

		boolean isCheck = false; // Assuming the King is not in check
		String target; // The algebric square to analyse

		String savedPosition = getPosition(); // Save the current position

		moveOnBoard(from, to); // Make the suggested movement
		changePlayer();
		String kingSquare = getKingSquare();
		String[] tabMoves = getAllValidMoves(false); // Get all valid moves for
														// the adversary

		for (int i = 0; i < tabMoves.length; i++) { // Check if each adversary
													// move can go at the king
													// square
			if (tabMoves[i] == null) {
				break;
			}
			target = tabMoves[i].substring(tabMoves[i].length() - 2);
			if (target.equals(kingSquare)) {
				isCheck = true;
				break;
			}
		}

		setPosition(savedPosition); // Restore to the current position

		if (isCheck) {
			return true;
		} else {
			return false;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if the White
	 * Castle Short is a valid move Parameters: None Return: TRUE if O-O is a
	 * valid move for white Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean whiteCastleShort() {

		// if king and rook hasn't move
		if (whiteCanCastleShort) {
			if (board[60] == Constant.WHITE_KING
					&& board[61] == Constant.FREE_SQUARE
					&& board[62] == Constant.FREE_SQUARE
					&& board[63] == Constant.WHITE_ROOK) {
				// check if king go or pass through an attacked square
				if (!kingIsInCheck(60, 61) && !kingIsInCheck(60, 62)) {
					return true;
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if the White
	 * Castle Long is a valid move Parameters: None Return: TRUE if O-O-O is a
	 * valid move for white Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean whiteCastleLong() {

		// if king and rook hasn't move
		if (whiteCanCastleLong) {
			if (board[60] == Constant.WHITE_KING
					&& board[59] == Constant.FREE_SQUARE
					&& board[58] == Constant.FREE_SQUARE
					&& board[57] == Constant.FREE_SQUARE
					&& board[56] == Constant.WHITE_ROOK) {
				// check if king go or pass through an attacked square
				if (!kingIsInCheck(60, 59) && !kingIsInCheck(60, 58)) {
					return true;
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if the Black
	 * Castle Short is a valid move Parameters: None Return: TRUE if O-O is a
	 * valid move for black Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean blackCastleShort() {

		// if king and rook hasn't move
		if (blackCanCastleShort) {
			if (board[4] == Constant.BLACK_KING
					&& board[5] == Constant.FREE_SQUARE
					&& board[6] == Constant.FREE_SQUARE
					&& board[7] == Constant.BLACK_ROOK) {
				// check if king go or pass through an attacked square
				if (!kingIsInCheck(4, 5) && !kingIsInCheck(4, 6)) {
					return true;
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if the Black
	 * Castle Long is a valid move Parameters: None Return: TRUE if O-O-O is a
	 * valid move for black Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean blackCastleLong() {

		// if king and rook hasn't move
		if (blackCanCastleLong) {
			if (board[4] == Constant.BLACK_KING
					&& board[3] == Constant.FREE_SQUARE
					&& board[2] == Constant.FREE_SQUARE
					&& board[1] == Constant.FREE_SQUARE
					&& board[0] == Constant.BLACK_ROOK) {
				// check if king go or pass through an attacked square
				if (!kingIsInCheck(4, 3) && !kingIsInCheck(4, 2)) {
					return true;
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Create the long algebric
	 * notation for a move. Ex: Nb8-d7, e4-e5, Bf8xc5 etc... Parameters: The
	 * piece value (1 to 6), the number of the squares from and to. Return: A
	 * string with the long algebric notation Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private String convertMoveLong(int piece, int from, int to) {

		String move;

		if (isPromotion) {
			move = sqAlg[from] + "-" + sqAlg[to] + "="
					+ getPieceNotation(piece);
		} else {
			if (board[to] == Constant.FREE_SQUARE) {
				move = getPieceNotation(piece) + sqAlg[from] + "-" + sqAlg[to];
			} else {
				move = getPieceNotation(piece) + sqAlg[from] + "x" + sqAlg[to];
			}

		}

		return move;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Create the short
	 * algebric notation for a move. Ex: Nd7, e5, Bxc5 etc... Parameters: The
	 * piece value (1 to 6), the number of the squares from and to. Return: A
	 * string with the short algebric notation Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private String convertMoveShort(int piece, int from, int to) {

		String move;
		String ret;
		char col;

		if (isPromotion) {
			move = sqAlg[to] + "=" + getPieceNotation(piece);
		} else {
			if (board[to] == Constant.FREE_SQUARE) {
				if (enPassant.equals(sqAlg[to]) && piece == Constant.PAWN) {
					col = getColumn(from);
					move = col + "x" + sqAlg[to];
				} else {
					move = getPieceNotation(piece) + sqAlg[to];
				}
			} else { // is a capture
				ret = getPieceNotation(piece);
				if (ret == "") {
					col = getColumn(from);
					move = col + "x" + sqAlg[to];
				} else {
					move = getPieceNotation(piece) + "x" + sqAlg[to];
				}
			}
		}

		return move;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Verify if a move is
	 * valid Parameters: The piece value (1 to 6), the number of the squares
	 * from and to. Return: TRUE if the suggested move is valid, otherwise FALSE
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean moveIsValid(int piece, int from, int to) {

		if (board[to] != Constant.FREE_SQUARE) { // check if the target square
													// has
			// ocupied for a piece of the same color
			if (whoPlays == Constant.WHITE) {
				if (board[to] < Constant.BLACK) {
					return false;
				}
			} else {
				if (board[to] > Constant.BLACK) {
					return false;
				}
			}
		}

		int x1 = from / 8; // convert the square number for coordinates (x, y)
							// where x=row and y=column
		int y1 = from % 8;
		int x2 = to / 8;
		int y2 = to % 8;

		boolean ret = false;

		if (piece == Constant.PAWN) {
			ret = validatePawn(x1, y1, x2, y2);
		}

		if (piece == Constant.QUEEN) {
			ret = validateQueen(x1, y1, x2, y2);
		}

		if (piece == Constant.ROOK) {
			ret = validateRook(x1, y1, x2, y2);
		}

		if (piece == Constant.BISHOP) {
			ret = validateBishop(x1, y1, x2, y2);
		}

		if (piece == Constant.KNIGHT) {
			ret = validateKnight(x1, y1, x2, y2);
		}

		if (piece == Constant.KING) {
			ret = validateKing(x1, y1, x2, y2);
		}

		if (ret) {
			return true;
		} else {
			return false;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validate and Make the
	 * Short Castle (O-O) at the board Parameters: None. Return: TRUE if castle
	 * could be made. Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean makeShortCastle() {

		if (whoPlays == Constant.WHITE) {
			if (whiteCanCastleShort) {
				if (kingIsInCheck()) {
					return false;
				}
				if (board[60] == Constant.WHITE_KING
						&& board[61] == Constant.FREE_SQUARE
						&& board[62] == Constant.FREE_SQUARE
						&& board[63] == Constant.WHITE_ROOK) {
					if (!kingIsInCheck(60, 61) && !kingIsInCheck(60, 62)) {
						moveOnBoard(60, 62); // move the king
						moveOnBoard(63, 61); // move the rook
						controlFiftyMovesRule(60, 62); // adjust fifty moves
														// rules
						controlCastle(60, 62); // adjust control castle
						changePlayer();
						return true;
					}
				}
			}
		} else {

			if (blackCanCastleShort) {
				if (kingIsInCheck()) {
					return false;
				}
				if (board[4] == Constant.BLACK_KING
						&& board[5] == Constant.FREE_SQUARE
						&& board[6] == Constant.FREE_SQUARE
						&& board[7] == Constant.BLACK_ROOK) {
					if (!kingIsInCheck(4, 5) && !kingIsInCheck(4, 6)) {
						moveOnBoard(4, 6); // move the king
						moveOnBoard(7, 5); // move the rook
						controlFiftyMovesRule(4, 6); // adjust fifty moves rules
						controlCastle(4, 6); // adjust control castle
						numMove++;
						changePlayer();
						return true;
					}
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validate and Make the
	 * Long Castle (O-O-O-) at the board Parameters: None. Return: TRUE if
	 * castle could be made. Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean makeLongCastle() {

		if (whoPlays == Constant.WHITE) {
			if (whiteCanCastleLong) {
				if (kingIsInCheck()) {
					return false;
				}
				if (board[60] == Constant.WHITE_KING
						&& board[59] == Constant.FREE_SQUARE
						&& board[58] == Constant.FREE_SQUARE
						&& board[57] == Constant.FREE_SQUARE
						&& board[56] == Constant.WHITE_ROOK) {
					if (!kingIsInCheck(60, 59) && !kingIsInCheck(60, 58)) {
						moveOnBoard(60, 58); // move the king
						moveOnBoard(56, 59); // move the rook
						controlFiftyMovesRule(60, 58); // adjust the fifty moves
														// rule
						controlCastle(60, 58); // adjust control castle
						changePlayer();
						return true;
					}
				}
			}
		} else {
			if (blackCanCastleLong) {
				if (kingIsInCheck()) {
					return false;
				}
				if (board[4] == Constant.BLACK_KING
						&& board[3] == Constant.FREE_SQUARE
						&& board[2] == Constant.FREE_SQUARE
						&& board[1] == Constant.FREE_SQUARE
						&& board[0] == Constant.BLACK_ROOK) {
					if (!kingIsInCheck(4, 3) && !kingIsInCheck(4, 2)) {
						moveOnBoard(4, 2); // move the king
						moveOnBoard(0, 3); // move the rook
						controlFiftyMovesRule(4, 2); // adjust the fifty moves
														// rule
						controlCastle(4, 2); // adjust control castle
						numMove++; // increment the next move number (only after
									// black moves)
						changePlayer();
						return true;
					}
				}
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Control the number of
	 * half-moves after a pawn move or a take of a piece Parameters: The squares
	 * FROM and TO that represent the move Return: Nothing Author: Sergio
	 * Batista Date: 31-jan-2012
	 */
	private void controlFiftyMovesRule(int from, int to) {

		if (board[from] == Constant.WHITE_PAWN
				|| board[from] == Constant.BLACK_PAWN
				|| board[to] != Constant.FREE_SQUARE) {
			numMovesLastPawn = 0;
		} else {
			numMovesLastPawn++;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Control if castles can
	 * be made after the suggested move Parameters: The squares FROM and TO that
	 * represent the move Return: Nothing Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private void controlCastle(int from, int to) {

		if (whoPlays == Constant.WHITE) {
			if (from == 60) {
				whiteCanCastleShort = false;
				whiteCanCastleLong = false;
			} else if (from == 56) {
				whiteCanCastleLong = false;
			} else if (from == 63) {
				whiteCanCastleShort = false;
			}
		} else {
			if (from == 4) {
				blackCanCastleShort = false;
				blackCanCastleLong = false;
			} else if (from == 0) {
				blackCanCastleLong = false;
			} else if (from == 7) {
				blackCanCastleShort = false;
			}
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Look for the King Square
	 * Parameters: None Return: The algebric square of the King (color depends
	 * on who plays) Author: Sergio Batista Date: 31-jan-2012
	 */
	private String getKingSquare() {

		int king;

		if (whoPlays == Constant.WHITE) {
			king = 26;
		} else {
			king = 16;
		}

		for (int i = 0; i < 64; i++) {
			if (board[i] == king) {
				return sqAlg[i];
			}
		}

		return "ERROR";
	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Return all the square
	 * numbers from a piece Ex. If the piece is 3 (Bishop) and who_plays is 20
	 * (Black) return the squares where is each black Bishop (23) Parameters:
	 * The number of the piece and the move in algebric notation Return: An
	 * array with all the squares with the same piece Author: Sergio Batista
	 * Date: 31-jan-2012
	 */
	private int[] getPieceSquare(int piece, String move) {

		int ind = 0;
		int sqPiece[] = new int[10];
		char col, tcol;

		if (piece == Constant.PAWN && move.length() > 2) {
			col = move.charAt(0);
		} else {
			col = 'x';
		}

		piece = piece + whoPlays;

		for (int i = 0; i < 64; i++) {
			if (board[i] == piece) {
				tcol = getColumn(i);
				if (col == 'x' || col == tcol) {
					sqPiece[ind] = i;
					ind++;
				}
			}
		}

		for (int i = ind; i < 10; i++) {
			sqPiece[i] = Constant.ERROR;
		}

		return sqPiece;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the color of a
	 * square Parameters: The number of a square Return: 10 if the square is
	 * WHITE, 20 for BLACK Author: Sergio Batista Date: 31-jan-2012
	 */
	private int getSquareColor(int square) {

		return sqColor[square];

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the color of a
	 * square Parameters: The algebric square Return: 10 if the square is WHITE,
	 * 20 for BLACK Author: Sergio Batista Date: 31-jan-2012
	 */
	private int getSquareColor(String square) {

		for (int i = 0; i < 64; i++) {
			if (square.equals(sqAlg[i])) {
				return sqColor[i];
			}
		}

		return Constant.ERROR;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the number of a
	 * square Parameters: The algebric square Return: The number of a square
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	public static int getSquareNumber(String square) {

		for (int i = 0; i < 64; i++) {
			if (square.equals(sqAlg[i])) {
				return i;
			}
		}

		return Constant.ERROR;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Make a move at the
	 * current board Parameters: The squares FROM and TO that represent the move
	 * Return: Nothing Author: Sergio Batista Date: 31-jan-2012
	 */
	private void moveOnBoard(int from, int to) {

		if (isEnPassant(to)) { // if en passant, clear the square where the pawn
								// has moved to at the first time (the 2nd
								// square)
			if (whoPlays == Constant.WHITE) {
				if (board[from] == Constant.WHITE_PAWN) {
					board[to + 8] = Constant.FREE_SQUARE;
				}
			} else {
				if (board[from] == Constant.BLACK_PAWN) {
					board[to - 8] = Constant.FREE_SQUARE;
				}
			}
		}

		if (board[from] == Constant.WHITE_PAWN && (to + 16 == from)) { // if
																		// pawn
																		// moved
																		// 2
			// squares, save
			// square that
			// can take en
			// passant
			enPassant = sqAlg[from - 8];
		} else if (board[from] == Constant.BLACK_PAWN && (from + 16 == to)) {
			enPassant = sqAlg[from + 8];
		} else {
			enPassant = "";
		}

		board[to] = board[from]; // change piece position on board
		board[from] = Constant.FREE_SQUARE;

		squareTo = to;
		squareFrom = from;

	}

	/**
	 * Set a clear Board and reset all information related to it Parameters:
	 * None Return: Nothing
	 */
	private void resetBoard() {
		int i;

		for (i = 0; i < 64; i++) {
			board[i] = Constant.FREE_SQUARE;
		}

		whiteCanCastleShort = false;
		whiteCanCastleLong = false;
		blackCanCastleShort = false;
		blackCanCastleLong = false;
		enPassant = "";
		numMovesLastPawn = 0;
		numMove = 1;
	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Set the last square that
	 * can be take as en passant (when a player move the pawn 2 squares, the
	 * first square is saved in a variable to control en passant moviment.
	 * Parameters: The algebric square that pawn has bypassed. Return: Nothing
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	private void setPosEnPassant(String alg) {

		enPassant = alg;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Set who plays, based in
	 * a fen information Parameters: The part of a fen string, that contain who
	 * plays information (w or b) Return: Nothing Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private void setPosWhoPlays(String fen) {

		char s;

		for (int i = 0; i < fen.length(); i++) {
			s = fen.charAt(i);
			switch (s) {
			case 'w':
				whoPlays = Constant.WHITE;
				break;
			case 'b':
				whoPlays = Constant.BLACK;
				break;
			}
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Set the castle status,
	 * based in a fen information Parameters: The part of a fen string, that
	 * contain castle information (w or b) Return: Nothing Author: Sergio
	 * Batista Date: 31-jan-2012
	 */
	private void setPosCastle(String fen) {

		char s;

		for (int i = 0; i < fen.length(); i++) {
			s = fen.charAt(i);
			switch (s) {
			case 'K':
				whiteCanCastleShort = true;
				break;
			case 'Q':
				whiteCanCastleLong = true;
				break;
			case 'k':
				blackCanCastleShort = true;
				break;
			case 'q':
				blackCanCastleLong = true;
				break;
			}
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Set a new position based
	 * on a fen string Parameters: The part of a fen string, that contain the
	 * position Return: Nothing Author: Sergio Batista Date: 31-jan-2012
	 */
	private void setPosPieces(String fen) {

		char s;
		int ind = 0;
		int xis;

		for (int i = 0; i < fen.length(); i++) { // Put each piece in the
													// respective square
			s = fen.charAt(i);
			if (s >= '0' && s <= '9') {
				xis = Character.digit(s, 10);
				for (int j = 0; j < xis; j++) {
					board[ind] = Constant.FREE_SQUARE;
					ind++;
				}
			} else {
				switch (s) {
				case '/':
					break;
				case 'K':
					board[ind] = Constant.WHITE_KING;
					ind++;
					break;
				case 'Q':
					board[ind] = Constant.WHITE_QUEEN;
					ind++;
					break;
				case 'R':
					board[ind] = Constant.WHITE_ROOK;
					ind++;
					break;
				case 'B':
					board[ind] = Constant.WHITE_BISHOP;
					ind++;
					break;
				case 'N':
					board[ind] = Constant.WHITE_KNIGHT;
					ind++;
					break;
				case 'P':
					board[ind] = Constant.WHITE_PAWN;
					ind++;
					break;
				case 'k':
					board[ind] = Constant.BLACK_KING;
					ind++;
					break;
				case 'q':
					board[ind] = Constant.BLACK_QUEEN;
					ind++;
					break;
				case 'r':
					board[ind] = Constant.BLACK_ROOK;
					ind++;
					break;
				case 'b':
					board[ind] = Constant.BLACK_BISHOP;
					ind++;
					break;
				case 'n':
					board[ind] = Constant.BLACK_KNIGHT;
					ind++;
					break;
				case 'p':
					board[ind] = Constant.BLACK_PAWN;
					ind++;
					break;
				}
			}
		}

	}

	/**
	 * Create an array to convert Algebric Notation (a1-h8) in numerical (0-63)
	 * and vice-versa Parameters: None Return: Nothing
	 */
	private void setAlgebric() {

		String tab[] = { "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8", "a7",
				"b7", "c7", "d7", "e7", "f7", "g7", "h7", "a6", "b6", "c6",
				"d6", "e6", "f6", "g6", "h6", "a5", "b5", "c5", "d5", "e5",
				"f5", "g5", "h5", "a4", "b4", "c4", "d4", "e4", "f4", "g4",
				"h4", "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", "a2",
				"b2", "c2", "d2", "e2", "f2", "g2", "h2", "a1", "b1", "c1",
				"d1", "e1", "f1", "g1", "h1" };

		for (int i = 0; i < 64; i++) {
			sqAlg[i] = tab[i];
		}

	}

	/**
	 * Create an array to store square colors Parameters: None Return: Nothing
	 */
	private static void setSquareColors() {
		boolean startWithWhite = true;
		sqColor[0] = Constant.WHITE;
		for (int i = 1; i < 64; i++) {
			if (i % 8 == 0) {
				startWithWhite = !startWithWhite;
			}
			if (startWithWhite) {
				if (i % 2 == 0) {
					sqColor[i] = Constant.WHITE;
				} else {
					sqColor[i] = Constant.BLACK;
				}
			} else {
				if (i % 2 == 0) {
					sqColor[i] = Constant.BLACK;
				} else {
					sqColor[i] = Constant.WHITE;
				}
			}

		}
	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Adjust the number of
	 * half moves after a pawn moviment Parameters: The new number to set this
	 * variable Return: Nothing Author: Sergio Batista Date: 31-jan-2012
	 */
	private void setPosNumMovesLastPawn(String num) {

		numMovesLastPawn = Integer.valueOf(num);

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Adjust the number of
	 * moves for the current position Parameters: The new number of moves
	 * Return: Nothing Author: Sergio Batista Date: 31-jan-2012
	 */
	private void setPosNumMoves(String num) {

		numMove = Integer.valueOf(num);

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if a square is
	 * free Parameters: The coordenates of the square (x1, y1) x = row (0 = top,
	 * 7 = down) y = column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1)
	 * Return: TRUE if that square is free Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private boolean isFreeSquare(int x1, int y1) {

		int square = x1 * 8 + y1;

		if (board[square] == Constant.FREE_SQUARE) {
			return true;
		} else {
			return false;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if has a enemy
	 * piece in a given square Parameters: The coordenates of the square (x1,
	 * y1) x = row (0 = top, 7 = down) y = column (0 = left, 7 = right) Ex: (0,0
	 * = a8) (7,7 = h1) Return: TRUE if has a enemy piece in that square Author:
	 * Sergio Batista Date: 31-jan-2012
	 */
	private boolean isEnemyPiece(int x1, int y1) {

		int square = x1 * 8 + y1;

		if (whoPlays == Constant.WHITE) {
			if (board[square] > Constant.BLACK) {
				return true;
			}
		} else {
			if (board[square] < Constant.BLACK
					&& board[square] > Constant.WHITE) {
				return true;
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if a square can
	 * used to take en passant Parameters: The number of the square Return: TRUE
	 * if the square can used to take en passant, FALSE otherwise Author: Sergio
	 * Batista Date: 31-jan-2012
	 */
	private boolean isEnPassant(int square) {

		if (enPassant != "") {
			int epSquare = getSquareNumber(enPassant);
			if (square == epSquare) {
				return true;
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if a square can
	 * used to take en passant Parameters: The coordenates of the square (x =
	 * row (0-7), y = column (0-7) Return: TRUE if the square can used to take
	 * en passant, FALSE otherwise Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean isEnPassant(int x, int y) {

		if (enPassant != "") {
			int square = getSquareNumber(enPassant);
			int x1 = square / 8;
			int y1 = square % 8;
			if (x1 == x && y1 == y) {
				return true;
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Split a FEN notation in
	 * various chunks (position, who plays, castle control, etc...) Parameters:
	 * The fen string Return: An array with each chunk Author: Sergio Batista
	 * Date: 31-jan-2012
	 */
	private String[] splitFEN(String fen) {

		char s;
		String myStr = "";
		String part[] = new String[6];
		int ind = 0;

		// divide the string in chunks at each blank character (' ')
		for (int i = 0; i < fen.length(); i++) {
			s = fen.charAt(i);
			if (s == ' ') {
				part[ind] = myStr;
				myStr = "";
				ind++;
			} else {
				myStr = myStr + s;
			}
		}

		part[ind] = myStr;
		return part;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validate a string with a
	 * FEN position Parameters: The position in FEN notation Return: TRUE if the
	 * FEN position is valid, FALSE otherwise Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private boolean validateFen(String fen) {

		boolean error = false;
		boolean y1, y2, y3, y4, y5, y6;
		char x;
		int countBlanks = 0;
		int countBars = 0;
		int countSquares = 0;
		int countColors = 0;
		int countCastle = 0;
		int countEpCol = 0;
		int countEpRow = 0;
		int countEpNone = 0;

		if (fen == null) {
			return false;
		}

		// check if the fen is too short
		if (fen.length() < 25) {
			error = true;
		}

		for (int i = 0; i < fen.length(); i++) {
			x = fen.charAt(i);
			if (x == ' ') {
				countBlanks++; // a FEN must have 5 spaces
			}
			if (x == '/') {
				countBars++; // a FEN must have 7 bars
			}
			if (x >= '0' && x <= '9' && countBlanks == 0) { // counting free
															// squares
				countSquares = countSquares + Character.digit(x, 10);
			}
			y1 = (x == 'K' || x == 'k' || x == 'Q' || x == 'q' || x == 'R'
					|| x == 'r' || x == 'B' || x == 'b' || x == 'N' || x == 'n'
					|| x == 'P' || x == 'p');
			if (y1 && countBlanks == 0) { // counting occupied squares
				countSquares++;
			}
			y2 = (x == 'w' || x == 'b');
			if (y2 && countBlanks == 1) { // counting who_plays info
				countColors++;
			}
			y3 = (x == 'K' || x == 'Q' || x == 'k' || x == 'q' || x == '-');
			if (y3 && countBlanks == 2) { // counting castle info
				countCastle++;
			}
			y4 = (x == 'a' || x == 'b' || x == 'c' || x == 'd' || x == 'e'
					|| x == 'f' || x == 'g' || x == 'h');
			if (y4 && countBlanks == 3) { // checking for a valid en passant
											// square
				countEpCol++;
			}
			y5 = (x == '3' || x == '6'); // checking for a valid en passant
											// square
			if (y5 && countBlanks == 3) {
				countEpRow++;
			}
			y6 = (x == '-'); // checking for none en passant info
			if (y6 && countBlanks == 3) {
				countEpNone++;
			}
			if ((x != ' ') && (x < '0' || x > '9')
					&& (countBlanks == 4 || countBlanks == 5)) {
				error = true; // checking for number of moves and 50 moves rule
			}

		}

		if (countSquares != 64 || countBars != 7 || countBlanks != 5
				|| countColors != 1 || countCastle < 1) {
			error = true;
		}

		if (countEpNone > 0) {
			if (countEpRow + countEpCol > 0) {
				error = true;
			}
		} else {
			if (countEpRow != 1 && countEpCol != 1) {
				error = true;
			}
		}

		if (error) {
			System.out.println("Invalid FEN");
			return false;
		} else {
			return true;
		}

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validade a Pawn movement
	 * Parameters: The coordenates of the square FROM (x1, y1) and the
	 * coordenates of the square TO (x2, y2) x = row (0 = top, 7 = down) y =
	 * column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1) Return: TRUE if is
	 * a valid movement Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean validatePawn(int x1, int y1, int x2, int y2) {

		boolean xis;

		if (whoPlays == Constant.WHITE) {
			// if the white pawn can move forwards
			xis = (x1 == x2 + 1 && y1 == y2)
					|| (x1 == x2 + 2 && x1 == 6 && y1 == y2 && isFreeSquare(
							x1 - 1, y1));
			if (xis) {
				if (isFreeSquare(x2, y2)) {
					return true;
				}
			}
			// if the white pawn can capture a piece
			xis = (x1 == x2 + 1 && y1 == y2 + 1 && isEnemyPiece(x2, y2)
					|| x1 == x2 + 1 && y1 == y2 - 1 && isEnemyPiece(x2, y2)
					|| x1 == x2 + 1 && y1 == y2 + 1 && isEnPassant(x2, y2) || x1 == x2 + 1
					&& y1 == y2 - 1 && isEnPassant(x2, y2));
			if (xis) {
				return true;
			}
		} else {
			// if the black pawn can move forwards
			xis = (x1 == x2 - 1 && y1 == y2)
					|| (x1 == x2 - 2 && x1 == 1 && y1 == y2 && isFreeSquare(
							x1 + 1, y1));
			if (xis) {
				if (isFreeSquare(x2, y2)) {
					return true;
				}
			}
			// if the black pawn can capture a piece
			xis = (x1 == x2 - 1 && y1 == y2 - 1 && isEnemyPiece(x2, y2)
					|| x1 == x2 - 1 && y1 == y2 + 1 && isEnemyPiece(x2, y2)
					|| x1 == x2 - 1 && y1 == y2 - 1 && isEnPassant(x2, y2) || x1 == x2 - 1
					&& y1 == y2 + 1 && isEnPassant(x2, y2));
			if (xis) {
				return true;
			}
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validade a King movement
	 * Parameters: The coordenates of the square FROM (x1, y1) and the
	 * coordenates of the square TO (x2, y2) x = row (0 = top, 7 = down) y =
	 * column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1) Return: TRUE if is
	 * a valid movement Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean validateKing(int x1, int y1, int x2, int y2) {

		boolean xis = (x1 == x2 - 1 && y1 == y2) || (x1 == x2 + 1 && y1 == y2)
				|| (x1 == x2 && y1 == y2 - 1) || (x1 == x2 && y1 == y2 + 1)
				|| (x1 == x2 - 1 && y1 == y2 + 1)
				|| (x1 == x2 - 1 && y1 == y2 - 1)
				|| (x1 == x2 + 1 && y1 == y2 + 1)
				|| (x1 == x2 + 1 && y1 == y2 - 1);

		if (xis) {
			return true;
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validade a Queen
	 * movement Parameters: The coordenates of the square FROM (x1, y1) and the
	 * coordenates of the square TO (x2, y2) x = row (0 = top, 7 = down) y =
	 * column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1) Return: TRUE if is
	 * a valid movement Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean validateQueen(int x1, int y1, int x2, int y2) {

		boolean xis = validateRook(x1, y1, x2, y2);

		if (xis) {
			return true;
		}

		xis = validateBishop(x1, y1, x2, y2);

		if (xis) {
			return true;
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validade a Knight
	 * movement Parameters: The coordenates of the square FROM (x1, y1) and the
	 * coordenates of the square TO (x2, y2) x = row (0 = top, 7 = down) y =
	 * column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1) Return: TRUE if is
	 * a valid movement Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean validateKnight(int x1, int y1, int x2, int y2) {

		boolean xis = (x1 == x2 - 2 && y1 == y2 + 1)
				|| (x1 == x2 - 2 && y1 == y2 - 1)
				|| (x1 == x2 - 1 && y1 == y2 - 2)
				|| (x1 == x2 - 1 && y1 == y2 + 2)
				|| (x1 == x2 + 2 && y1 == y2 + 1)
				|| (x1 == x2 + 2 && y1 == y2 - 1)
				|| (x1 == x2 + 1 && y1 == y2 - 2)
				|| (x1 == x2 + 1 && y1 == y2 + 2);

		if (xis) {
			return true;
		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validade a Bishop
	 * movement Parameters: The coordenates of the square FROM (x1, y1) and the
	 * coordenates of the square TO (x2, y2) x = row (0 = top, 7 = down) y =
	 * column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1) Return: TRUE if is
	 * a valid movement Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean validateBishop(int x1, int y1, int x2, int y2) {

		if (x1 > x2 && y1 < y2) {
			// if the Bishop can move Northwest
			while (x1 > x2 && y1 < y2) {
				x1--;
				y1++;
				if (x1 == x2 && y1 == y2) {
					return true;
				} else {
					if (!isFreeSquare(x1, y1)) {
						return false;
					}
				}
			}
			return false;
		}

		if (x1 > x2 && y1 > y2) {
			// if the Bishop can move Northest
			while (x1 > x2 && y1 > y2) {
				x1--;
				y1--;
				if (x1 == x2 && y1 == y2) {
					return true;
				} else {
					if (!isFreeSquare(x1, y1)) {
						return false;
					}
				}
			}
			return false;
		}

		if (x1 < x2 && y1 > y2) {
			// if the Bishop can move Southwest
			while (x1 < x2 && y1 > y2) {
				x1++;
				y1--;
				if (x1 == x2 && y1 == y2) {
					return true;
				} else {
					if (!isFreeSquare(x1, y1)) {
						return false;
					}
				}
			}
			return false;
		}

		if (x1 < x2 && y1 < y2) {
			// if the Bishop can move Southest
			while (x1 < x2 && y1 < y2) {
				x1++;
				y1++;
				if (x1 == x2 && y1 == y2) {
					return true;
				} else {
					if (!isFreeSquare(x1, y1)) {
						return false;
					}
				}
			}
			return false;
		}
		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Validade a Rook movement
	 * Parameters: The coordenates of the square FROM (x1, y1) and the
	 * coordenates of the square TO (x2, y2) x = row (0 = top, 7 = down) y =
	 * column (0 = left, 7 = right) Ex: (0,0 = a8) (7,7 = h1) Return: TRUE if is
	 * a valid movement Author: Sergio Batista Date: 31-jan-2012
	 */
	private boolean validateRook(int x1, int y1, int x2, int y2) {

		if (y1 == y2) {
			if (x1 > x2) {
				// if the Rook can move forward
				while (x1 > x2) {
					x1--;
					if (x1 == x2) {
						return true;
					} else {
						if (!isFreeSquare(x1, y1)) {
							return false;
						}
					}
				}
			} else {
				// if the Rook can move backward
				while (x1 < x2) {
					x1++;
					if (x1 == x2) {
						return true;
					} else {
						if (!isFreeSquare(x1, y1)) {
							return false;
						}
					}
				}
			}
		} else {
			if (x1 == x2) {
				if (y1 < y2) {
					// if the Rook can move left
					while (y1 < y2) {
						y1++;
						if (y1 == y2) {
							return true;
						} else {
							if (!isFreeSquare(x1, y1)) {
								return false;
							}
						}
					}
				} else {
					// if the Rook can move right
					while (y1 > y2) {
						y1--;
						if (y1 == y2) {
							return true;
						} else {
							if (!isFreeSquare(x1, y1)) {
								return false;
							}
						}
					}
				}

			}

		}

		return false;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the piece from a
	 * algebric move Parameters: The algebric move Return: The number of the
	 * piece in that move Author: Sergio Batista Date: 31-jan-2012
	 */
	private int getPiece(String move) {

		if (move.charAt(0) == 'K') {
			return Constant.KING;
		}

		if (move.charAt(0) == 'Q') {
			return Constant.QUEEN;
		}

		if (move.charAt(0) == 'R') {
			return Constant.ROOK;
		}

		if (move.charAt(0) == 'B') {
			return Constant.BISHOP;
		}

		if (move.charAt(0) == 'N') {
			return Constant.KNIGHT;
		}

		return Constant.PAWN;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the piece
	 * abbreviation, used in the algebric notation Parameters: The number of the
	 * piece Return: The simbol of the piece (K, Q, R, B or N). If a Pawn,
	 * returns an empty string: "" Author: Sergio Batista Date: 31-jan-2012
	 */
	private String getPieceNotation(int piece) {

		if (piece == Constant.KING) {
			return "K";
		}

		if (piece == Constant.QUEEN) {
			return "Q";
		}

		if (piece == Constant.ROOK) {
			return "R";
		}

		if (piece == Constant.BISHOP) {
			return "B";
		}

		if (piece == Constant.KNIGHT) {
			return "N";
		}

		return "";

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the column from a
	 * square Parameters: The number of a square Return: The algebric column
	 * ('a', 'b', 'c' etc...) Author: Sergio Batista Date: 31-jan-2012
	 */
	private char getColumn(int square) {

		char[] tab = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
		int x = square % 8;

		return tab[x];

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Get the row from a
	 * square Parameters: The number of a square Return: The algebric row ('1'
	 * (first white row), '2', '3' etc...) Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private char getRow(int square) {

		int x = Math.abs(square / 8 - 8);
		return Character.forDigit(x, 10);

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Eliminate de '+' and '#'
	 * signals from a move Parameters: The string with the move Return: A string
	 * with the same move without the above signals Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private String cleanNotation(String move) {
		
		move = move.trim();

		char arr[] = move.toCharArray();

		if (arr[move.length() - 1] == '+' || arr[move.length() - 1] == '#') {
			move = move.substring(0, move.length() - 1);
		}

		return move;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Check if two (or more)
	 * pieces can go for the same square (Ex: Nd7, Nf6-d7, Nb8-d7) Parameters:
	 * The arrays with the short and long notation, the number of elements that
	 * will be compared Return: An array with the undoubtful notation (Nbd7)
	 * Author: Sergio Batista Date: 31-jan-2012
	 */
	private String[] checkForDuplicity(String[] movShort, String[] movLong,
			int ind) {

		for (int i = 0; i < ind; i++) {
			for (int j = i; j < ind; j++) {
				if (movShort[i].equals(movShort[j]) && i != j) {
					movShort[i] = fixNotation(movShort[i], movLong[i],
							movLong[j]);
					movShort[j] = fixNotation(movShort[j], movLong[j],
							movLong[i]);
					// j = i-1;
				}
			}
			// System.out.println(mov_short[i]);
		}

		return movShort;

	}

	/*
	 * ==========================================================================
	 * ======================================= Summary: Fix the notation when
	 * two pieces can go for the same square Parameters: The strings with the
	 * short, long and rival notation (Ex: Nd7, Nf6-d7, Nb8-d7) Return: A string
	 * with the undoubtful notation (Nbd7) Author: Sergio Batista Date:
	 * 31-jan-2012
	 */
	private String fixNotation(String movShort, String movLong,
			String movLongRival) {

		char v1, v2, v3, v4, v5; // to represent all individual character of the
									// mov_short string
		boolean isPawn = false; // assuming that is not a pawn

		if (movShort.length() == 2) { // it's a pawn move
			movShort = "P" + movShort;
			movLong = "P" + movLong;
			movLongRival = "P" + movLongRival;
			isPawn = true;
		}

		char extra;
		char arrShort[] = movShort.toCharArray();
		char arrLong[] = movLong.toCharArray();
		char arrRival[] = movLongRival.toCharArray();

		if (arrLong[1] == arrRival[1]) { // if the row is the same, consider the
											// column as a differential
			extra = arrLong[2];
		} else {
			extra = arrLong[1];
		}

		if (isPawn) { // if is a pawn, must be a capture (otherwise it's
						// impossible two pawns goes to the same square)
			v1 = extra;
			v2 = 'x';
			v3 = arrShort[1];
			v4 = arrShort[2];
			v5 = ' ';
		} else { // rearrange the string to include the extra information (the
					// column or the row)
			v1 = arrShort[0];
			v2 = extra;
			v3 = arrShort[1];
			if (movShort.length() > 3) {
				v4 = arrShort[2];
				v5 = arrShort[3];
			} else {
				v4 = arrShort[2];
				v5 = ' ';
			}
		}

		char xis[] = { v1, v2, v3, v4 };
		String s = new String(xis);
		if (movShort.length() > 3) {
			s = s + v5;
		}
		return s;

	}

}
